package net;

import model.eval.Test;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
/*

    This file is part of Logica-Logike.

    Logica-Logike is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation version 3 of the License.

    Logica-Logike is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Logica-Logike.  If not, see <http://www.gnu.org/licenses/>.

 */
/**
 * Clase cliente, usada obtener la evaluacion y enviarla al servidor cuando sea el cliente lo disponga;
 *
 * @author Jose Martin Rozanec;
 */
public class Client extends Thread {
    private ObjectInputStream input;        // to read the socket
    private ObjectOutputStream output;    // towrite on the socket
    private Socket socket;
    private UserData userData;
    private boolean testResolved;
    private Test test;

    /**
     * Constructor;
     *
     * @param ip;
     */
    public Client(String ip) {
        // we use "localhost" as host name, the server is on the same machine
        // but you can put the "real" server name or IP address
        testResolved = false;
        try {
            socket = new Socket(ip, 5041);
        }
        catch (Exception e) {
            System.out.println("Error connectiong to server:" + e);
            return;
        }
        System.out.println("Connection accepted " +
                socket.getInetAddress() + ":" +
                socket.getPort() + "\n");

        /* Creating both Data Streams */
        try {
            input = new ObjectInputStream(socket.getInputStream());
            output = new ObjectOutputStream(socket.getOutputStream());
        }
        catch (IOException e) {
            System.out.println("Exception creating new Input/output Streams: " + e);
            return;
        }
        // my connection is established
    }

    //recibir client ID
    //escribir userData
    //recibir y mandar test
    //recibir clientID
    /**
     * Metodo run, sigue el siguiente protocolo:
     * - recibir client ID
     * - escribir userData
     * - recibir y mandar test
     * - recibir clientID
     */
    public void run() {
        try {
            System.out.println("Reading clientID...\nClientID: " + (Long) input.readObject());
        } catch (IOException e) {
            System.out.println("Error writting to the socket: " + e);
            return;
        } catch (ClassNotFoundException e) {
            System.out.println("ClassNotFoundException...___");
        }
        try {
            System.out.println("Sending user data...");
            output.writeObject(userData);
            System.out.println("User data was sent...");
        } catch (IOException e) {
            System.out.println("Error writting to the socket: " + e);
            return;
        }
        try {
            test = (Test) input.readObject();
            System.out.println("Retrieving test...\nRetrieved test: " + test);
            System.out.println("Information succesfully exchanged!");
        } catch (IOException e) {
            System.out.println("Error writting to the socket: " + e);
            return;
        } catch (ClassNotFoundException e) {
            System.out.println("ClassNotFoundException...___");
        }
        try {
            System.out.println("ACK received test...");
            output.writeObject(new Long(0));
            System.out.println("ACK sent...");
        } catch (IOException e) {
            System.out.println("Error writting to the socket: " + e);
            return;
        }

        try {
            System.out.println("Waiting to send the test...");
            while (!testResolved) {
                System.out.println("TestResolved? "+testResolved);
                sleep(5000);
            }
            output.writeObject(test);
            System.out.println("Resolved test was sent...");
        } catch (IOException e) {
            System.out.println("Error writting to the socket: " + e);
            return;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * Permite conocer si la instancia cliente se halla conectada;
     *
     * @return boolean;
     */
    public boolean isConnected() {
        if (socket != null) {
            return socket.isConnected();
        }
        return false;
    }

    /**
     * Permite setear la evaluacion resuelta;
     *
     * @param test;
     */
    public void setResolvedTest(Test test) {
        this.test = test;
        this.testResolved = true;
    }

    /**
     * Permite acceder el user data;
     *
     * @return UserData;
     */
    public UserData getUserData() {
        return userData;
    }

    /**
     * Permite setear los datos de usuario por el objeto UserData;
     *
     * @param userData;
     */
    public void setUserData(UserData userData) {
        this.userData = userData;
    }

    /**
     * Permite acceder a la evaluacion;
     *
     * @return Test;
     */
    public Test getTest() {
        return test;
    }
}